require 'digest/sha1'
class User < ActiveRecord::Base
  has_one :profile, :dependent => :destroy
  has_many :created_courses, :class_name => "Course"
  has_and_belongs_to_many :courses
  # Usar polimorfismo sigue siendo una chinga en Rails 1.2 (espero que en Rails
  # 2.0 esto mejore). Es más fácil si separamos eventos y asignaciones en dos
  # relasiones distintas:
  has_many :events
  has_many :created_assignments, :class_name => "Assignment"
  has_many :assignment_answers 
  has_many :graded_answers, :class_name => "AssignmentAnswer", :foreign_key => "grader_id"

  # Virtual attribute for the unencrypted password
  attr_accessor :password
  # Atributo virtual para el ultimo login (antes de actualizarlo).
  attr_accessor :last_last_login

  validates_presence_of     :login, :email, :message => 'debe estar presente.'
  validates_presence_of     :password,                   :if => :password_required?, :message => 'debe estar presente.'
  validates_presence_of     :password_confirmation,      :if => :password_required?, :message => 'debe estar presente.'
  validates_length_of       :password, :within => 8..40, :if => :password_required?, :too_long => 'demasiado largo (máximo 40 cars.)', :too_short => 'demasiado corto (mínimo 8 cars.).'
  validates_confirmation_of :password,                   :if => :password_required?, :message => 'debe ser idéntico las dos veces.' 
  validates_length_of       :login,    :within => 3..40, :too_long => 'demasiado largo (máximo 40 cars.)', :too_short => 'demasiado corto (mínimo 3 cars.)'
  validates_length_of       :email,    :within => 3..100, :too_long => 'demasiado largo (máximo 100 cars.)', :too_short => 'demasiado corto (mínimo 3 cars.)'
  validates_format_of       :email, :with => /(^([^@\s]+)@((?:[-_a-z0-9]+\.)+[a-z]{2,})$)|(^$)/i, :message => 'es inválido'
  validates_uniqueness_of   :login, :email, :case_sensitive => false, :message => 'ya existe.'
  validates_presence_of     :kind, :message => 'WTF'
  before_save :encrypt_password


  # Authenticates a user by their login name and unencrypted password.  Returns the user or nil.
  def self.authenticate(login, password)
    u = find_by_login(login) # need to get the salt
    u && u.authenticated?(password) ? u : nil
  end

  # Encrypts some data with the salt.
  def self.encrypt(password, salt)
    Digest::SHA1.hexdigest("--#{salt}--#{password}--")
  end

  # Encrypts the password with the user salt
  def encrypt(password)
    self.class.encrypt(password, salt)
  end

  def authenticated?(password)
    if crypted_password == encrypt(password) and activation_code.nil?
      return true
    else
      return false
    end
  end

  def remember_token?
    remember_token_expires_at && Time.now.utc < remember_token_expires_at 
  end

  # These create and unset the fields required for remembering users between browser closes
  def remember_me
    self.remember_token_expires_at = 2.weeks.from_now.utc
    self.remember_token            = encrypt("#{email}--#{remember_token_expires_at}")
    save(false)
  end

  def forget_me
    self.remember_token_expires_at = nil
    self.remember_token            = nil
    save(false)
  end

  def is_administrator?
    self[:kind] == 'Admin'
  end
  
  alias is_admin? is_administrator?

  def is_student?
    self[:kind] == "Student"
  end

  def is_instructor?
    self[:kind] == "Instructor"
  end

  protected
    # before filter 
    def encrypt_password
      return if password.blank?
      self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
      self.crypted_password = encrypt(password)
    end
    
    def password_required?
      crypted_password.blank? || !password.blank?
    end
end
